#pragma once

#include <iostream>
#include <sstream>

namespace cal
{

#define WHERE_STATEMENT std::string{__FILE__} + ":" + std::to_string(__LINE__)
#define DEV_CERR(msg) std::cerr << "dev-error: " << msg
#define DEV_MARK(msg) std::string{"["} + msg + "]"

#define CAL_DEV_FAILED_MESSAGE(msg)              \
    do {                                         \
        std::ostringstream oss;                  \
        oss << DEV_MARK(WHERE_STATEMENT) << msg; \
        DEV_CERR(oss.str());                     \
        exit(1);                                 \
    } while (0)

// condition
// - true:  passed
// - false: failed
#define CAL_DEV_ASSERT(condition)                                      \
    do {                                                               \
        if (!(condition)) {                                            \
            CAL_DEV_FAILED_MESSAGE(DEV_MARK(#condition) << "failed");  \
        }                                                              \
    } while (0)

// condition
// - true:  passed
// - false: failed
#define CAL_DEV_ASSERT_MESSAGE(condition, msg)                                  \
    do {                                                                        \
        if (!(condition)) {                                                     \
            CAL_DEV_FAILED_MESSAGE(DEV_MARK(#condition) << "failed: " << msg);  \
        }                                                                       \
    } while (0)
    
// 用于 switch default 处，避免有时候因为忘记更新 case 导致错误
// * 仅当 defaut 一定不使用时
#define CAL_THROW_SWITCH_DEFAULT \
    CAL_DEV_ASSERT_MESSAGE(false, "Failure to update the case value in time")

}   // namespace cal
